package Recursion_05;

/*
 * @Author 罗
 * @date 2020/3/15 - 3:17 下午
 *
 * 递归需要遵守的重要规则
 * 1.执行一个方法时，就创建一个新的受保护的独立空间（栈空间）
 * 2.方法的局部变量是独立的，不会相互影响，比如方法的普通参数
 * 3.如果方法中，使用的是引用类型变量，就会共享该引用类型的数据
 * 4.递归必须向退出递归的调价逼近，否则就是无限递归，死龟了
 * 5.当一个方法执行完毕，或者遇到return，就会返回，遵守谁调用，就将结果返回给谁
 *      同时当方法执行完毕或者返回时，该方法也就执行完毕
 */

import org.junit.Test;

import java.util.Arrays;

public class MiGong_01 {

    @Test
    public void miGong(){
//            用一个二维数组表示迷宫
        int[][] map = new int[8][25];
//        给迷宫的边缘加上墙
//        墙用1来表示
        for (int i = 0; i < 8; i++) {
            if(i==0 || i==map.length - 1) {
//            墙的上下设置为1
                for (int j = 0; j < map[0].length - 1; j++) {
                    map[i][j] = 1;
                }
            }
//            墙的左右设置为1
            map[i][0] = 1;
            map[i][map[0].length - 1] = 1;
        }
/*        map[3][1] = 1;
        map[3][2] = 1;*/
        /*
        * 随机地图生成
        * */
        double rate = 0.2;//墙出现的概率
        for (int i = 1; i < map.length - 1; i++) {
            for (int j = 1; j < map[i].length - 2; j++) {
                if((Math.random()) > 1 - rate){

                    map[i][j] = 1;
                }
            }
        }



        System.out.println("遍历数组，查看迷宫");
        for (int[] ints : map) {
            for (int anInt : ints) {
                System.out.print(anInt+"\t");
            }
            System.out.println();
        }

        if(setWay(map,1,1)) {
            System.out.println("路径已经找到");
        }else{
            System.err.println("路径没有找到");
        }
        for (int[] ints : map) {
            for (int anInt : ints) {

                System.out.print(anInt+"\t");
            }
            System.out.println();
        }
    }

    /**
     * 使用递归回溯来给小球找路
     * 说明：
     *      如果小球能 到达map[6][5]说明通路找到
     *      约定：当map[i][j]为0时-->该点没有被走过
     *                      为1时-->表示墙
     *                      为2时-->表示通路可以走
     *                      为3时-->表示该点已经走过，但是走不通
     *           在走迷宫时，需要定义一个策略（方法）
     *                  下->右->上->左
     *                  如果这些方向都走不通，再回溯
     * @param map 表示地图
     * @param i   表示地图从那一个位置开始触发的y轴坐标
     * @param j   表示地图从那一个位置开始触发的x轴坐标
     * @return    如果找到通路，返回true，否则返回false
     */
    public static boolean setWay(int[][] map, int i,  int j){
        /*
        * 每次进入递归方法，首先判断返回条件
        *   如果抵达了终点map[6][5]，说明路已经找到，返回true
        * */
        if(map[map.length-2][map[0].length-2] == 2){
            return true;
        }else if(map[i][j] == 0){
            /*
            * 该点没有被走过，进行测试
            * 通路还没有找到，根据 下->右->上->左 的顺序依次寻找通路
            *
            * 1.首先假设该点能够走通，以本点为基础，寻找通路
            * */

            map[i][j] = 2;

            if(setWay(map,i+1,j)){
//                往下走可以走通
                return true;
            }else if(setWay(map,i,j+1)){
//                往右走可以走通
                return true;
            }else if(setWay(map,i-1,j)){
//                往上走可以走通
                return true;
            }else if(setWay(map,i,j-1)){
//                往左走可以走通
                return true;
            }else{
//                以本点为基础的上下左右四个方向都走不通，设置本节点为3（该点已经走过，但是走不通）
                map[i][j] = 3;
                return false;
            }
        }else{
//            该点不是0--->该点为 1(墙),2(已经走过，不能走回头路),3(该点已经走过，但是走不通) -->都走不通
            return false;
        }
    }
}
